package util

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"time"
)

func init() {
	if !CheckFileIsExist(LogPath) {
		os.Create(LogPath) //创建文件
	}
}

type LogStruct struct {
	Type     string   `json:"type"`
	TypeData TypeData `json:"typeData"`
	UniqId   int64    `json:"uniqId"`
	Content  string   `json:"content"`
	Create   int64    `json:"create"`
}

func GetLogStruct(logType, content string, typeData TypeData) LogStruct {
	var logData LogStruct
	logData.Type = logType
	logData.TypeData = typeData
	logData.Content = content
	logData.UniqId = typeData.UniqId
	return logData
}

func Log(logData LogStruct) error {

	var err error = nil
	file, err := os.OpenFile(LogPath, os.O_WRONLY|os.O_APPEND, 0666) //打开文件  读加写权限
	defer file.Close()
	if err != nil {
		panic(err)
	}

	write := bufio.NewWriter(file) // 创建新的 Writer 对象
	if err != nil {
		panic(err)
	}

	logData.Create = time.Now().Unix()
	data, _ := json.Marshal(logData)
	_, err = write.WriteString(string(data) + "\n")
	write.Flush()
	return err
}

func GetLog(maxLine int) {
	f, err := os.OpenFile(LogPath, os.O_RDONLY, 0666) //打开文件  读加写权限
	defer f.Close()
	if err != nil {
		panic(err)
	}
	buff := make([]byte, 0, 4096)
	char := make([]byte, 1)

	// 查询文件大小
	stat, _ := f.Stat()
	filesize := stat.Size()

	var cursor int64 = 0
	cnt := 0
	for {
		cursor -= 1
		_, _ = f.Seek(cursor, io.SeekEnd)
		_, err = f.Read(char)
		if err != nil {
			fmt.Println("日志文件未读取到内容")
			break
		}

		if char[0] == '\n' {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				printLog(logData) // 打印读取到的行
				cnt++
				if cnt == maxLine { // 超过数量退出
					break
				}
			}
			buff = buff[:0]
		} else {
			buff = append(buff, char[0])
		}

		if cursor == -filesize {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				printLog(logData) // 打印最后一行
			}
			break
		}
	}
}

func GetUniqIdLog(uniqId int64) {
	f, err := os.OpenFile(LogPath, os.O_RDONLY, 0666) //打开文件  读加写权限
	defer f.Close()
	if err != nil {
		panic(err)
	}

	buff := make([]byte, 0, 4096)
	char := make([]byte, 1)

	// 查询文件大小
	stat, _ := f.Stat()
	filesize := stat.Size()

	var cursor int64 = 0
	for {
		cursor -= 1
		_, _ = f.Seek(cursor, io.SeekEnd)
		_, err = f.Read(char)
		if err != nil {
			fmt.Println("日志文件未读取到内容")
			break
		}
		if char[0] == '\n' {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				if logData.TypeData.UniqId == uniqId {
					printLog(logData)
				}
			}
			buff = buff[:0]
		} else {
			buff = append(buff, char[0])
		}

		if cursor == -filesize {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				if logData.TypeData.UniqId == uniqId {
					printLog(logData)
				}
			}
			break
		}
	}
}

func GetTypeLog(logType string) {
	f, err := os.OpenFile(LogPath, os.O_RDONLY, 0666) //打开文件  读加写权限
	defer f.Close()
	if err != nil {
		panic(err)
	}

	buff := make([]byte, 0, 4096)
	char := make([]byte, 1)

	// 查询文件大小
	stat, _ := f.Stat()
	filesize := stat.Size()

	var cursor int64 = 0
	for {
		cursor -= 1
		_, _ = f.Seek(cursor, io.SeekEnd)
		_, err = f.Read(char)
		if err != nil {
			fmt.Println("日志文件未读取到内容")
			break
		}
		if char[0] == '\n' {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				if logData.Type == logType {
					printLog(logData)
				}
			}
			buff = buff[:0]
		} else {
			buff = append(buff, char[0])
		}

		if cursor == -filesize {
			if len(buff) > 0 {
				revers(buff)
				var logData LogStruct
				_ = json.Unmarshal(buff, &logData)
				if logData.Type == logType {
					printLog(logData)
				}
			}
			break
		}
	}
}

func revers(s []byte) {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

func printLog(logData LogStruct) {
	ColorPrint(LogTypeColorMap[logData.Type], strings.ToUpper(logData.Type))
	fmt.Println(" ", logData.Content)
	Print("Date:", FrontTime(logData.Create), "| uniqId", logData.TypeData.UniqId)
	fmt.Println()
}
